/*
 * 描          述:  <描述>
 * 修  改   人:  Administrator
 * 修改时间:  2019年12月11日
 * <修改描述:>
 */
package com.tx.component.social.support.gitee;

import java.util.List;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;

import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;

import com.tx.component.security.exception.SocialAuthorizeException;
import com.tx.component.social.SocialLoginPlugin;
import com.tx.component.social.context.SocialLoginContext;
import com.tx.component.social.model.SocialAccountType;
import com.tx.component.social.model.SocialAccountTypeEnum;
import com.tx.core.exceptions.util.AssertUtils;
import com.tx.core.util.MessageUtils;

import me.zhyd.oauth.config.AuthConfig;
import me.zhyd.oauth.config.AuthConfig.AuthConfigBuilder;
import me.zhyd.oauth.model.AuthCallback;
import me.zhyd.oauth.model.AuthResponse;
import me.zhyd.oauth.model.AuthUser;
import me.zhyd.oauth.request.AuthDefaultRequest;
import me.zhyd.oauth.request.AuthGiteeRequest;
import me.zhyd.oauth.request.AuthRequest;

/**
 * Gitee登陆插件<br/>
 * 
 * @author  Administrator
 * @version  [版本号, 2019年12月11日]
 * @see  [相关类/方法]
 * @since  [产品/模块版本]
 */
public class GELoginPlugin extends SocialLoginPlugin<GELoginPluginConfig> {
    
    public static final String SCOPE_USER_INFO = "user_info";
    
    public static final String SCOPE_PROJECTS = "projects";
    
    public static final String SCOPE_PULL_REQUESTS = "pull_requests";
    
    public static final String SCOPE_ISSUES = "issues";
    
    public static final String SCOPE_NOTES = "notes";
    
    public static final String SCOPE_KEYS = "keys";
    
    public static final String SCOPE_HOOK = "hook";
    
    public static final String SCOPE_groups = "groups";
    
    public static final String SCOPE_GISTS = "gists";
    
    public static final String SCOPE_ENTERPRISES = "enterprises";
    
    /** code请求URL */
    //private static final String CODE_REQUEST_URL = "https://gitee.com/oauth/authorize";
    
    /** uid请求URL */
    //scope表示权限范围，有以下选项，请求时使用空格隔开
    //user_info projects pull_requests issues notes keys hook groups gists enterprises
    //private static final String UID_REQUEST_URL = "https://gitee.com/oauth/token";
    
    /** userInfo请求URL */
    //private static final String USER_INFO_REQUEST_URL = "https://gitee.com/api/v5/user";
    
    /** "REDIRECT_URL"属性名称 */
    private static final String REDIRECT_URL_ATTRIBUTE_NAME = GELoginPlugin.class
            .getName() + ".REDIRECT_URL";
    
    /** 有效时间 */
    //private static final long expiration = 10 * 60 * 1000;
    
    /**
     * @return
     */
    @Override
    public String getName() {
        return "Gitee登陆插件";
    }
    
    /**
     * @return
     */
    @Override
    public String getVersion() {
        return "1.0";
    }
    
    /**
     * @return
     */
    @Override
    public SocialAccountType getSocialAccountType() {
        return SocialAccountTypeEnum.GE;
    }
    
    /**
     * @return
     */
    @Override
    public String getPrefix() {
        return "plugin.login.ge";
    }
    
    /**
     * 获取code的handle<br/>
     * @param viewName
     * @param redirectUri
     * @param scope
     * @param request
     * @return
     */
    @Override
    public String authorize(String redirectUri, String state,
            List<String> scopes, HttpServletRequest request) {
        AssertUtils.notEmpty(redirectUri, "redirectUri is empty.");
        
        //写入state值
        HttpSession session = request.getSession();
        SocialLoginContext.getContext().saveState(session, state);
        session.setAttribute(REDIRECT_URL_ATTRIBUTE_NAME, redirectUri);
        
        GELoginPluginConfig config = getConfig();
        AuthConfigBuilder acbuilder = AuthConfig.builder()
                .clientId(config.getClientId())
                .clientSecret(config.getClientSecret())
                .redirectUri(redirectUri);
        if (!CollectionUtils.isEmpty(scopes)) {
            acbuilder.scopes(scopes);
        }
        AuthRequest authRequest = new AuthGiteeRequest(acbuilder.build());
        String authorize = authRequest.authorize(state);
        return authorize;
        
        //ModelAndView mview = new ModelAndView();
        //Map<String, String> parameterMap = new LinkedHashMap<>();
        //parameterMap.put("response_type", "code");
        //parameterMap.put("client_id", config.getClientId());
        //parameterMap.put("redirect_uri", redirectUri);
        //parameterMap.put("state", state);
        //
        //mview.setViewName(viewName);
        //mview.addObject("requestUrl", CODE_REQUEST_URL);
        //mview.addObject("parameterMap", parameterMap);
        //List<NameValuePair> nameValuePairs = new ArrayList<>();
        //for (Entry<String, String> entryTemp : parameterMap.entrySet()) {
        //    if (StringUtils.isEmpty(entryTemp.getKey())) {
        //        continue;
        //    }
        //    nameValuePairs.add(new BasicNameValuePair(entryTemp.getKey(),
        //            entryTemp.getValue()));
        //}
        //String url = CODE_REQUEST_URL;
        //try {
        //    url = url + (StringUtils.contains(url, "?") ? "&" : "?")
        //            + EntityUtils.toString(
        //                    new UrlEncodedFormEntity(nameValuePairs, "UTF-8"));
        //} catch (ParseException | IOException e) {
        //    throw new SILException("拼接redirectUrl异常.", e);
        //}
        //生成视图逻辑
        //if (StringUtils.isEmpty(viewName)) {
        //    mview.setViewName("redirect:" + url);
        //} else {
        //    mview.setViewName(viewName);
        //}
        //return mview;
    }
    
    /**
     * @param code
     * @param state
     * @param request
     * @return
     * @throws SocialAuthorizeException
     */
    @Override
    public AuthUser login(String code, String state, HttpServletRequest request)
            throws SocialAuthorizeException {
        HttpSession session = request.getSession();
        String sessionState = SocialLoginContext.getContext().getState(session);
        if (!StringUtils.equals(state, sessionState)) {
            throw new SocialAuthorizeException(MessageUtils.format(
                    "state value is invalid.request_state:{}  session_state:{}",
                    state,
                    sessionState));
        }
        
        GELoginPluginConfig config = getConfig();
        AuthConfigBuilder acbuilder = AuthConfig.builder()
                .clientId(config.getClientId())
                .clientSecret(config.getClientSecret());
        AuthDefaultRequest authRequest = new AuthGiteeRequest(
                acbuilder.ignoreCheckState(true).build());
        
        @SuppressWarnings("unchecked")
        AuthResponse<AuthUser> resp = authRequest
                .login(AuthCallback.builder().code(code).build());
        if (!resp.ok()) {
            throw new SocialAuthorizeException("获取第三方登陆用户信息失败.");
        }
        
        AuthUser au = resp.getData();
        return au;
    }
    
    ///**
    // * 获取AccessToken<br/>
    // *    https://open.weibo.com/wiki/Oauth/access_token
    // * @param code
    // * @param state
    // * @param request
    // * @return
    // * @throws SocialAuthorizeException
    // */
    //public SocialAccessToken getAccessToken(String code, String state,
    //        HttpServletRequest request) throws SocialAuthorizeException {
    //    HttpSession session = request.getSession();
    //    String sessionState = SocialLoginContext.getContext().getState(session);
    //    if (!StringUtils.equals(state, sessionState)) {
    //        throw new SocialAuthorizeException(MessageUtils.format(
    //                "state value is invalid.request_state:{}  session_state:{}",
    //                state,
    //                sessionState));
    //    }
    //    
    //    GELoginPluginConfig config = getConfig();
    //    AuthDefaultRequest authRequest = new AuthGiteeRequest(
    //            AuthConfig.builder()
    //                    .clientId(config.getClientId())
    //                    .clientSecret(config.getClientSecret())
    //                    .build());
    //    AuthResponse<AuthUser> resp = authRequest.login(AuthCallback.builder().code(code).build());
    //    
    //    //AuthResponseStatus.SUCCESS
    //    authRequest.login(AuthCallback.builder().code(code).)
    //    //从会话中获取redirectUri
    //    String redirectUri = (String) session
    //            .getAttribute(REDIRECT_URL_ATTRIBUTE_NAME);
    //    GELoginPluginConfig config = getConfig();
    //    Map<String, String> parameterMap = new HashMap<>();
    //    parameterMap.put("grant_type", "authorization_code");
    //    String appKey = config.getClientId();
    //    String appSecret = config.getClientSecret();
    //    parameterMap.put("client_id", appKey);
    //    parameterMap.put("client_secret", appSecret);
    //    parameterMap.put("code", code);
    //    parameterMap.put("redirect_uri", redirectUri);
    //    String result = HttpClientUtils.post(UID_REQUEST_URL, parameterMap);
    //    
    //    logger.info(
    //            "--- getAccessToken:{client_id:{},client_secret:{},code:{},result:{}}",
    //            appKey,
    //            appSecret,
    //            code,
    //            result);
    //    //getAccessToken:{client_id:e89c345917ce6375e634,client_secret:c9757c70a8af2c01e2a85b5f6e06fc240c122867,code:48896d56a152d946da65,result:access_token=dc400027043a1980222dcdf3fb90858b1b7ac75b&scope=&token_type=bearer}
    //    //access_token=dc400027043a1980222dcdf3fb90858b1b7ac75b&scope=&token_type=bearer
    //    //Map<String, String> tokenMap = WebUtils.parse(result);
    //    //String accessToken = tokenMap.get("access_token");
    //    JsonNode tokenJNode = JsonUtils.toTree(result);
    //    String accessToken = tokenJNode.get("access_token").asText();
    //    
    //    SocialAccessToken token = new SocialAccessToken(
    //            SocialAccountTypeEnum.GE);
    //    token.setAccessToken(accessToken);
    //    token.setExpiresIn((new Date()).getTime() + expiration);
    //    if (StringUtils.isEmpty(token.getAccessToken())) {
    //        throw new SocialAuthorizeException("获取AccessToken失败.");
    //    }
    //    return token;
    //}
    //
    ///**
    // * 获取用户信息<br/>
    // * @param accessToken
    // * @param request
    // * @return
    // */
    //@Override
    //public SocialUserInfo getUserInfo(SocialAccessToken accessToken,
    //        HttpServletRequest request) {
    //    AssertUtils.notNull(accessToken, "accessToken is null.");
    //    AssertUtils.notEmpty(accessToken.getAccessToken(),
    //            "accessToken.accessToken is empty.");
    //    
    //    Map<String, String> params = new HashMap<String, String>();
    //    params.put("access_token", accessToken.getAccessToken());
    //    
    //    String result = HttpClientUtils.get(USER_INFO_REQUEST_URL, params);
    //    logger.info(
    //            "--- GHLoginPlugin.getUserInfo:{access_token:{},openid:{},result:{}}",
    //            accessToken.getAccessToken(),
    //            accessToken.getUniqueId(),
    //            result);
    //    //从接口中提取数据
    //    //getUserInfo:{access_token:b7ae403f31c13fb524c9777b7aed8aa3824eb475,openid:null,result:{"login":"240638006","id":2492318,"node_id":"MDQ6VXNlcjI0OTIzMTg=","avatar_url":"https://avatars3.githubusercontent.com/u/2492318?v=4","gravatar_id":"","url":"https://api.github.com/users/240638006","html_url":"https://github.com/240638006","followers_url":"https://api.github.com/users/240638006/followers","following_url":"https://api.github.com/users/240638006/following{/other_user}","gists_url":"https://api.github.com/users/240638006/gists{/gist_id}","starred_url":"https://api.github.com/users/240638006/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/240638006/subscriptions","organizations_url":"https://api.github.com/users/240638006/orgs","repos_url":"https://api.github.com/users/240638006/repos","events_url":"https://api.github.com/users/240638006/events{/privacy}","received_events_url":"https://api.github.com/users/240638006/received_events","type":"User","site_admin":false,"name":"Tim.PQY","company":"ChongQingTianXinWangLuoKeJiYouXianGongSi","blog":"","location":null,"email":"240638006@qq.com","hireable":true,"bio":null,"public_repos":14,"public_gists":0,"followers":1,"following":2,"created_at":"2012-10-05T07:58:47Z","updated_at":"2020-01-02T03:53:42Z"}}
    //    //{"login":"240638006","id":2492318,"node_id":"MDQ6VXNlcjI0OTIzMTg=","avatar_url":"https://avatars3.githubusercontent.com/u/2492318?v=4","gravatar_id":"","type":"User","site_admin":false,"name":"Tim.PQY","company":"ChongQingTianXinWangLuoKeJiYouXianGongSi","blog":"","location":null,"email":"240638006@qq.com","hireable":true,"bio":null,"public_repos":14,"public_gists":0,"followers":1,"following":2,"created_at":"2012-10-05T07:58:47Z","updated_at":"2020-01-02T03:53:42Z"}
    //    //Map<String, String> userMap = WebUtils.parse(result);
    //    JsonNode node = JsonUtils.toTree(result);
    //    String uniqueId = node.get("id").asText();
    //    String username = node.get("login").asText();
    //    String headImgUrl = node.get("avatar_url") != null
    //            ? node.get("avatar_url").asText()
    //            : null;
    //    String name = node.get("name").asText();
    //    String location = node.get("location") != null
    //            ? node.get("location").asText()
    //            : null;
    //    String company = node.get("company") != null
    //            ? node.get("company").asText()
    //            : null;
    //    String blog = node.get("blog") != null ? node.get("blog").asText()
    //            : null;
    //    String email = node.get("email") != null ? node.get("email").asText()
    //            : null;
    //    
    //    //SocialUserInfo
    //    SocialUserInfo user = new SocialUserInfo();
    //    user.setId(uniqueId);
    //    user.setSocialUsername(username);
    //    user.setHeadImgUrl(headImgUrl);
    //    user.setSex(null);
    //    user.setUniqueId(uniqueId);
    //    
    //    JSONObject json = user.getAttributeJSONObject();
    //    json.put("name", name);
    //    json.put("location", location);
    //    json.put("company", company);
    //    json.put("blog", blog);
    //    json.put("email", email);
    //    return user;
    //}
    //
    ///**
    // * 获取登陆用户的第三方唯一键<br/>
    // * @param accessToken
    // * @param request
    // * @return
    // * @throws SocialAuthorizeException
    // */
    //@Override
    //public String getUniqueId(SocialAccessToken accessToken,
    //        HttpServletRequest request) throws SocialAuthorizeException {
    //    AssertUtils.notNull(accessToken, "accessToken is null.");
    //    AssertUtils.notEmpty(accessToken.getAccessToken(),
    //            "accessToken.accessToken is empty.");
    //    
    //    SocialUserInfo userInfo = getUserInfo(accessToken, request);
    //    String uniqueId = userInfo.getUniqueId();
    //    return uniqueId;
    //}
}
